package main

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"time"
)

func Str2Int(str string) int {
	val, _ := strconv.ParseInt(str, 10, 32)
	return int(val)
}
func Str2Int64(str string) int64 {
	if str == "" {
		return 0
	}
	val, _ := strconv.ParseInt(str, 10, 64)
	return int64(val)
}

// Log 打印日志，日志在调试环境下和生产环境下都会显示。
func Log(a ...interface{}) {
	dd := make([]interface{}, 0)
	dd = append(dd, time.Now().Format("2006-01-02 15:04:05"))
	for _, k := range a {
		dd = append(dd, k)
	}
	fmt.Println(dd...)
}
func QueryUnescape(sv string) string {
	svv0, _ := url.PathUnescape(sv)
	svv, err00 := url.PathUnescape(svv0)
	if err00 != nil {
		return sv
	}
	return svv
}

// ParseUrl 解析URL
func ParseUrl(urlstr string) (status int, AllPath []string, UrlParams map[string]interface{}, data map[string]interface{}) {
	UrlParams = make(map[string]interface{})
	data = make(map[string]interface{})
	WenHao := false
	AllPath = make([]string, 0)
	status = 1

	PathStart := 0
	urlBytes := []byte(urlstr)

	ParamsValueIndex := -1
	ParamsKeyIndex := -1

	CurKey := ""
	CurValue := ""

	for i := 0; i < len(urlBytes); i++ {

		if urlBytes[i] == 47 && WenHao == false {
			if i > PathStart {
				sv := string(urlBytes[PathStart:i])
				svv := QueryUnescape(sv)
				AllPath = append(AllPath, svv)
			}
			PathStart = i + 1
		}
		if urlBytes[i] == 63 && WenHao == false {
			sv := string(urlBytes[PathStart:i])
			svv := QueryUnescape(sv)
			AllPath = append(AllPath, svv)

			WenHao = true
			PathStart = i + 1

			ParamsKeyIndex = i + 1
		}
		if WenHao == true {
			if urlBytes[i] == 61 && ParamsKeyIndex > -1 {

				sv := string(urlBytes[ParamsKeyIndex:i])

				CurKey = QueryUnescape(sv)
				ParamsKeyIndex = -1
				ParamsValueIndex = i + 1
			}
			if urlBytes[i] == 38 && ParamsValueIndex > -1 {
				sv := string(urlBytes[ParamsValueIndex:i])

				CurValue = QueryUnescape(sv)
				ParamsValueIndex = -1
				ParamsKeyIndex = i + 1
				UrlParams[CurKey] = CurValue

				if CurKey == "data" {
					json.Unmarshal([]byte(CurValue), &data)
				}

			}
		}
	}
	if WenHao == false {
		sv := string(urlBytes[PathStart:])
		svv := QueryUnescape(sv)
		AllPath = append(AllPath, svv)
	} else {
		if ParamsValueIndex >= 0 {
			sv := string(urlBytes[ParamsValueIndex:])

			CurValue = QueryUnescape(sv)
			UrlParams[CurKey] = CurValue

			if CurKey == "data" {
				json.Unmarshal([]byte(CurValue), &data)
			}
		}

	}
	if len(AllPath) != 5 {
		status = 0
		return
	}

	status = 1

	return
}

// ParseUrlNoCheck 解析URL
func ParseUrlNoCheck(urlstr string) (AllPath []string, UrlParams map[string]string, data map[string]string) {
	UrlParams = make(map[string]string)
	data = make(map[string]string)
	WenHao := false
	AllPath = make([]string, 0)

	PathStart := 0
	urlBytes := []byte(urlstr)

	ParamsValueIndex := -1
	ParamsKeyIndex := -1

	CurKey := ""
	CurValue := ""

	for i := 0; i < len(urlBytes); i++ {

		if urlBytes[i] == 47 && WenHao == false {
			if i > PathStart {
				sv := string(urlBytes[PathStart:i])
				svv := QueryUnescape(sv)
				AllPath = append(AllPath, svv)
			}
			PathStart = i + 1
		}
		if urlBytes[i] == 63 && WenHao == false {
			sv := string(urlBytes[PathStart:i])
			svv := QueryUnescape(sv)
			AllPath = append(AllPath, svv)

			WenHao = true
			PathStart = i + 1

			ParamsKeyIndex = i + 1
		}
		if WenHao == true {
			if urlBytes[i] == 61 && ParamsKeyIndex > -1 {

				sv := string(urlBytes[ParamsKeyIndex:i])

				CurKey = QueryUnescape(sv)
				ParamsKeyIndex = -1
				ParamsValueIndex = i + 1
			}
			if urlBytes[i] == 38 && ParamsValueIndex > -1 {
				sv := string(urlBytes[ParamsValueIndex:i])

				CurValue = QueryUnescape(sv)
				ParamsValueIndex = -1
				ParamsKeyIndex = i + 1
				UrlParams[CurKey] = CurValue

				if CurKey == "data" {
					json.Unmarshal([]byte(CurValue), &data)
				}

			}
		}
	}
	if WenHao == false {
		sv := string(urlBytes[PathStart:])
		svv := QueryUnescape(sv)
		AllPath = append(AllPath, svv)
	} else {
		if ParamsValueIndex >= 0 {
			sv := string(urlBytes[ParamsValueIndex:])

			CurValue = QueryUnescape(sv)
			UrlParams[CurKey] = CurValue

			if CurKey == "data" {
				json.Unmarshal([]byte(CurValue), &data)
			}
		}

	}

	return
}
func SuccessJson(w http.ResponseWriter, Data interface{}, Info InfoStruct) {

	res := ReturnMsg{}
	res.ErrorCode = 0
	res.Error = "成功"
	if Data == "" {
		res.Data = make(map[string]interface{})
	} else {
		res.Data = Data
	}

	//fmt.Println()

	jsonData, _ := json.Marshal(res)
	ReturnStr(w, string(jsonData), Info)

}

func ErrorJson(w http.ResponseWriter, ErrorCode int, Error string, Info InfoStruct) {
	res := ReturnMsg{}
	res.ErrorCode = ErrorCode
	res.Error = Error
	res.Data = make(map[string]interface{})
	jsonData, _ := json.Marshal(res)
	Log("出现错误", Error, "请求数据", Info.UrlPath, "请求消息", Info.Body)
	ReturnStr(w, string(jsonData), Info)
}

// 成功返回接口
func ReturnStr(w http.ResponseWriter, Data string, Info InfoStruct) {
	if Info.IsGzip == true {
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("content-type", "application/json;charset=utf-8")
		f, f0 := GzipStrNoBase64([]byte(Data))
		if f0 == true {
			Data = string(f)
		}
	}
	fmt.Fprint(w, Data)
}

// GetIP 获取远程IP
func GetIP(r *http.Request) ([]string, error) {

	ip, isIP := r.Header["X-Original-Forwarded-For"]
	if isIP == true && len(ip) >= 1 {
		return ip, nil
	}

	ip, isIP = r.Header["X-Real-Ip"]
	if isIP == true && len(ip) >= 1 {
		return ip, nil
	}

	ip, isIP = r.Header["X-Forwarded-For"]
	if isIP == true && len(ip) >= 1 {
		return ip, nil
	}

	ip0, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return []string{ip0}, err
	}

	if net.ParseIP(ip0) != nil {
		return []string{ip0}, nil
	}

	return []string{""}, errors.New("no valid ip found")
}
func GzipStrNoBool(str string) string {
	//var b bytes.Buffer
	//gz, _ := gzip.NewWriterLevel(&b, 1)
	//if _, err := gz.Write([]byte(str)); err != nil {
	//	return "", false
	//}
	//if err := gz.Flush(); err != nil {
	//	return "", false
	//}
	//if err := gz.Close(); err != nil {
	//	return "", false
	//}
	//encoded := base64.StdEncoding.EncodeToString(b.Bytes())
	//return encoded, true
	//return b.Bytes()

	var in bytes.Buffer
	w := gzip.NewWriter(&in)
	w.Write([]byte(str))
	w.Close()
	sEnc := base64.StdEncoding.EncodeToString(in.Bytes())
	return sEnc
}
func GzipStr(str string) (string, bool) {
	//var b bytes.Buffer
	//gz, _ := gzip.NewWriterLevel(&b, 1)
	//if _, err := gz.Write([]byte(str)); err != nil {
	//	return "", false
	//}
	//if err := gz.Flush(); err != nil {
	//	return "", false
	//}
	//if err := gz.Close(); err != nil {
	//	return "", false
	//}
	//encoded := base64.StdEncoding.EncodeToString(b.Bytes())
	//return encoded, true
	//return b.Bytes()

	var in bytes.Buffer
	w := gzip.NewWriter(&in)
	w.Write([]byte(str))
	w.Close()
	sEnc := base64.StdEncoding.EncodeToString(in.Bytes())
	return sEnc, true
}
func GzipStrNoBase64(str []byte) ([]byte, bool) {
	var b bytes.Buffer
	gz, _ := gzip.NewWriterLevel(&b, 1)
	if _, err := gz.Write(str); err != nil {
		fmt.Println("GzipStrNoBase64 Error1", err)
		return []byte(""), false
	}
	if err := gz.Flush(); err != nil {
		fmt.Println("GzipStrNoBase64 Error2", err)
		return []byte(""), false
	}
	if err := gz.Close(); err != nil {
		fmt.Println("GzipStrNoBase64 Error3", err)
		return []byte(""), false
	}
	//encoded := base64.StdEncoding.EncodeToString(b.Bytes())
	//return encoded, true
	return b.Bytes(), true

	//var in bytes.Buffer
	//w := gzip.NewWriter(&in)
	//w.Write(str)
	//w.Close()
	//return in.Bytes(), true
}
func StrvalDefault(data interface{}, defaultv string) string {
	if data == nil {
		return defaultv
	}

	mm := data.(string)
	if mm == "" {
		return defaultv
	}
	return mm
}

func Strval(value interface{}) string {
	var key string
	key = ""
	if value == nil {
		return key
	}

	if reflect.TypeOf(value).Kind() == reflect.Float64 {
		ft := value.(float64)
		return strconv.FormatFloat(ft, 'f', -1, 64)
	}
	if reflect.TypeOf(value).Kind() == reflect.Float32 {
		ft := value.(float32)
		return strconv.FormatFloat(float64(ft), 'f', -1, 64)
	}
	if reflect.TypeOf(value).Kind() == reflect.Int {
		it := value.(int)
		return strconv.Itoa(it)
	}
	if reflect.TypeOf(value).Kind() == reflect.Uint {
		it := value.(uint)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Int8 {
		it := value.(int8)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Uint8 {
		it := value.(uint8)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Int16 {
		it := value.(int16)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Uint16 {
		it := value.(uint16)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Int32 {
		it := value.(int32)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Uint32 {
		it := value.(uint32)
		return strconv.Itoa(int(it))
	}
	if reflect.TypeOf(value).Kind() == reflect.Int64 {
		it := value.(int64)
		return strconv.FormatInt(it, 10)
	}
	if reflect.TypeOf(value).Kind() == reflect.Uint64 {
		it := value.(uint64)
		return strconv.FormatUint(it, 10)
	}
	if reflect.TypeOf(value).Kind() == reflect.String {
		return value.(string)
	}
	if reflect.TypeOf(value).Kind() == reflect.Array || reflect.TypeOf(value).Kind() == reflect.Slice || reflect.TypeOf(value).Kind() == reflect.Map {
		newValue, _ := json.Marshal(value)
		return string(newValue)
	}
	return value.(string)
}
